Longest Increasing Subsequence (nlogn) Algorithm
The Longest Increasing Subsequence (nlogn) Algorithm is an efficient algorithm for finding the longest increasing subsequence within a given sequence of numbers in a time complexity of O(nlogn). An increasing subsequence refers to a subsequence of elements in which the elements are in strictly increasing order. The nlogn algorithm is an improvement over the traditional dynamic programming approach, which has a time complexity of O(n^2). By leveraging binary search, the nlogn algorithm reduces the time complexity while maintaining accuracy in finding the longest increasing subsequence.
The nlogn algorithm works by iteratively building a list of active lists, which maintains the smallest tail elements of all active lists of varying lengths. The algorithm traverses the input sequence and, for each element, performs a binary search on the active lists to find the correct position to insert or update the element. If the element is smaller than the smallest tail element, the algorithm creates a new active list with the current element. If the element is greater than the largest tail element, it clones the largest active list and extends it with the current element. If the element falls between the smallest and largest tail elements, the algorithm finds the appropriate active list and replaces its tail element with the current element. The length of the longest increasing subsequence is equal to the number of active lists at the end of the traversal.
//Program to calculate length of longest increasing subsequence in an array
// in O(n log n)
// tested on : https://cses.fi/problemset/task/1145/
#include <iostream>
using namespace std;
int LIS(int arr[], int n)
{
set < int > active; // The current built LIS.
active.insert(arr[0]);
// Loop through every element.
for (int i = 1; i < n; ++i)
{
auto get = active.lower_bound(arr[i]);
if (get == active.end())
{
active.insert(arr[i]);
} // current element is the greatest so LIS increases by 1.
else
{
int val = * get; // we find the position where arr[i] will be in the LIS. If it is in the LIS already we do nothing
if (val > arr[i])
{
// else we remove the bigger element and add a smaller element (which is arr[i]) and continue;
active.erase(get);
active.insert(arr[i]);
}
}
}
return active.size(); // size of the LIS.
}
int main(int argc, char const * argv[])
{
int n;
cout << "Enter size of array: ";
cin >> n;
int a[n];
cout << "Enter array elements: ";
for (int i = 0; i < n; ++i)
{
cin >> a[i];
}
cout << LIS(a, n) << endl;
return 0;
}